Creating animations and timelines using the Kanzi Engine API

The Kanzi animation system consists of animations and timelines. Animations define how values of specific type change in time, and timelines map animations to the properties of objects you want to animate.

You can use the Kanzi Engine API to create animations and timelines:

Creating from-to animations using the Kanzi Engine API

From-to animation defines from which to which value to change the value of a property. You can omit either of these values to animate either from the current value or to the current value of the property. From-to animations use an easing curve that defines the rate of change for the animation. You can use one of the easing curves that comes with Kanzi, or define your own.

To create a from-to animation:

// Create a from-to animation that uses the linear easing function and is two seconds long.
// As a starting value, the animation takes the current value of the property in the node you want to animate.
// The animation sets the final value of the property in the node you animate to 200.
// You set which node this animation animates in the timeline.
FloatLinearFromToAnimationSharedPtr linearAnimation = FloatLinearFromToAnimation::create(domain, chrono::seconds(2), nullopt, 200.0f);

To animate a property value in a node using a from-to animation:

// Create a property timeline and apply the linearAnimation from-to animation to the Layout Width property
// to animate the width of the current node.
PropertyAnimationTimelineSharedPtr propertyTimeline = PropertyAnimationTimeline::create(domain, ".", Node::WidthProperty, linearAnimation);

To animate a property field value in a node using a from-to animation:

// Create a property field animation timeline and apply it to the Render Transformation property of the current node.
PropertyFieldAnimationTimelineSharedPtr propertyFieldTimeline = PropertyFieldAnimationTimeline::create(domain, ".", Node2D::RenderTransformationProperty);
// Scale the current node on the x axis by animating the Scale X property field of the Render Transformation property
// with the linearAnimation from-to animation.
propertyFieldTimeline->addEntry(PropertyFieldScaleX, linearAnimation);

To create a float from-to animation that uses the back easing curve and the ease out easing mode:

// Define the FloatBackFromToAnimation to use float values and Back easing function.
typedef FromToAnimation<float, BackEasingFunction> FloatBackFromToAnimation;
typedef shared_ptr<FloatBackFromToAnimation> FloatBackFromToAnimationSharedPtr;
// Create a from-to animation that uses the back easing function and is 5000 milliseconds long.
// The animation sets the starting value of the property in the node you want to animate to 100,
// and the final value of that property to 300.
FloatBackFromToAnimationSharedPtr backAnimation = FloatBackFromToAnimation::create(domain, chrono::milliseconds(5000), nullopt, 300.0f);
// Set the easing mode of the backAnimation from-to animation to Ease out.
backAnimation->setEasingMode(AnimationEaseOut);

To play an animation regardless of the timeline type:

// Create the playback context and the timeline playback for the node defined in the item2d.
SceneGraphTimelinePlaybackContext context(*item2d);
// Create the playback for the timeline defined in the propertyFieldTimeline.
TimelinePlaybackSharedPtr playback = propertyFieldTimeline->createPlayback(context);
// Start the animation.
domain->getRootTimelineClock()->addTimelinePlayback(playback);

Creating keyframe animations using the Kanzi Engine API

Keyframe animation uses keyframes that define the property value and time at which the animation reaches that value. In Kanzi you can create linear, step, and Bézier spline keyframes.

To create a keyframe animation:

// Create a float keyframe animation.
FloatKeyframeAnimationSharedPtr keyframeAnimation = FloatKeyframeAnimation::create(domain);
// Create and add keyframes to the keyframe animation. This keyframe animation contains two linear keyframes.
// Create a linear keyframe at second 0 with the value 0.
keyframeAnimation->addLinearKeyframe(chrono::seconds::zero(), 0.0f);
// Create a linear keyframe at second 1 with the value 100.
keyframeAnimation->addLinearKeyframe(chrono::seconds(1), 100.0f);

To animate a property value in a node using a keyframe animation:

// Create a property timeline and apply the keyframeAnimation keyframe animation to the Layout Width property
// to animate the width of the current node.
PropertyAnimationTimelineSharedPtr propertyTimeline = PropertyAnimationTimeline::create(domain, ".", Node2D::WidthProperty, keyframeAnimation);

To animate a property field value in a node using a keyframe animation:

// Create a property field animation timeline and apply it to the Render Transformation property of the current node.
PropertyFieldAnimationTimelineSharedPtr propertyFieldTimeline = PropertyFieldAnimationTimeline::create(domain, ".", Node2D::RenderTransformationProperty);
// Rotate the current node by animating the Rotation Z property field of the Render Transformation property
// with the keyframeAnimation keyframe animation.
propertyFieldTimeline->addEntry(PropertyFieldRotationZ, keyframeAnimation);

To create a keyframe animation that uses Bezier keyframes to move an object on a sideways figure eight shaped path:

// Create two float keyframe animations: one to animate the object on the x axis,
// the other to animate the object on the y axis.
// Create float keyframe animation keyframeAnimationX that uses linear keyframes
// to animate the movement of the object on the x axis.
FloatKeyframeAnimationSharedPtr keyframeAnimationX = FloatKeyframeAnimation::create(domain);
// Create a linear keyframe at second 0 with the value 0.
keyframeAnimationX->addLinearKeyframe(chrono::seconds::zero(), 0.0f);
// Create a linear keyframe at second 4 with the value 4.
// At this keyframe the object reaches the furthest point on the x axis.
keyframeAnimationX->addLinearKeyframe(chrono::seconds(4), 4.0f);
// Create a linear keyframe at second 8 with the value 0.
// At this keyframe the object returns to the same position it had at the first keyframe.
keyframeAnimationX->addLinearKeyframe(chrono::seconds(8), 0.0f);

// Create float keyframe animation keyframeAnimationY that uses Bezier keyframes
// to animate the movement of the object on the y axis.
FloatKeyframeAnimationSharedPtr keyframeAnimationY = FloatKeyframeAnimation::create(domain);
// Create a linear keyframe at second 0 with the value 0. When you use Bezier keyframes,
// you can use any type of keyframe for the first keyframe, because you need this keyframe
// only to provide the information for the starting position.
keyframeAnimationY->addLinearKeyframe(chrono::seconds::zero(), 0.0f);
// Create a Bezier keyframe at second 4 with the value 0 and two control points.
// You use the control points to set the position of the keyframe.
keyframeAnimationY->addBezierKeyframe(chrono::seconds(4), 0.0f, Vector2(0.5f, 4.0f), Vector2(0.5f, -4.0f));
// Create a Bezier keyframe at second 8 with the value 0 and two control points.
// This keyframe uses the same control points, but because the keyframeAnimationX
// animation moves the object on the x axis back to its starting position, this keyframe
// is a mirror image of the previous keyframe.
keyframeAnimationY->addBezierKeyframe(chrono::seconds(8), 0.0f, Vector2(0.5f, 4.0f), Vector2(0.5f, -4.0f));

// Create a property field animation timeline and apply it to the Render Transformation property of the current node.
PropertyFieldAnimationTimelineSharedPtr timeline = PropertyFieldAnimationTimeline::create(domain, ".", Node3D::RenderTransformationProperty);
// Move the current node on the x axis by animating the Translation X property field of the Render Transformation property
// with the keyframeAnimationX keyframe animation.
timeline->addEntry(PropertyFieldTranslationX, keyframeAnimationX);
// Move the current node on the y axis by animating the Translation Y property field of the Render Transformation property
// with the keyframeAnimationY keyframe animation.
timeline->addEntry(PropertyFieldTranslationY, keyframeAnimationY);

To play an animation regardless of the timeline type:

// Create the playback context and the timeline playback for the node defined in the item2d.
SceneGraphTimelinePlaybackContext context(*item2d);
// Create the playback for the timeline defined in the propertyFieldTimeline.
TimelinePlaybackSharedPtr playback = propertyFieldTimeline->createPlayback(context);
// Start the animation.
domain->getRootTimelineClock()->addTimelinePlayback(playback);

Creating property timelines using the Kanzi Engine API

Property timeline applies an animation to a property of an object. For example, to change the layout size of an Image node, use the property timeline to animate the Layout Width and Layout Height properties of the node.

To create a property timeline:

// Create a property timeline and apply the linearAnimation animation to the Layout Width property
// to animate the width of the current node.
PropertyAnimationTimelineSharedPtr propertyTimeline = PropertyAnimationTimeline::create(domain, ".", Node::WidthProperty, linearAnimation);

To play an animation regardless of the timeline type:

// Create the playback context and the timeline playback for the node defined in the item2d.
SceneGraphTimelinePlaybackContext context(*item2d);
// Create the playback for the timeline defined in the propertyFieldTimeline.
TimelinePlaybackSharedPtr playback = propertyFieldTimeline->createPlayback(context);
// Start the animation.
domain->getRootTimelineClock()->addTimelinePlayback(playback);

Creating property field timelines using the Kanzi Engine API

Property field timeline applies an animation to one or more fields of a property of an object. For example, you can use a separate animation for each color channel to change the color of the text in a Text Block node.

To create a property field timeline:

// Create a property field timeline and apply it to the Render Transformation property of the current node.
PropertyFieldAnimationTimelineSharedPtr propertyFieldTimeline = PropertyFieldAnimationTimeline::create(domain, ".", Node2D::RenderTransformationProperty);
// Scale the current node on the x axis by animating the Scale X property field of the Render Transformation property
// with the linearAnimation animation.
propertyFieldTimeline->addEntry(PropertyFieldScaleX, linearAnimation);

To play an animation regardless of the timeline type:

// Create the playback context and the timeline playback for the node defined in the item2d.
SceneGraphTimelinePlaybackContext context(*item2d);
// Create the playback for the timeline defined in the propertyFieldTimeline.
TimelinePlaybackSharedPtr playback = propertyFieldTimeline->createPlayback(context);
// Start the animation.
domain->getRootTimelineClock()->addTimelinePlayback(playback);

Creating parallel timelines using the Kanzi Engine API

Parallel timeline allows you to group timelines which Kanzi plays at the same time. A parallel timeline ends when the animations in the last child timeline end. Use this timeline to organize collections of timelines and create a composition of timelines.

When you add to a parallel timeline child timelines, the union of the child timelines forms the content of the parallel timeline. This means that all playback properties of the parallel timeline are applied to its child timelines.

To create a parallel timeline:

// Create a parallel timeline.
ParallelTimelineSharedPtr parallelTimeline = ParallelTimeline::create(domain);
// Add propertyTimeline and propertyFieldTimeline timelines to the parallel timeline. Parallel timeline plays
// both timelines at the same time.
parallelTimeline->addChild(propertyTimeline);
parallelTimeline->addChild(propertyFieldTimeline);

To play an animation regardless of the timeline type:

// Create the playback context and the timeline playback for the node defined in the item2d.
SceneGraphTimelinePlaybackContext context(*item2d);
// Create the playback for the timeline defined in the propertyFieldTimeline.
TimelinePlaybackSharedPtr playback = propertyFieldTimeline->createPlayback(context);
// Start the animation.
domain->getRootTimelineClock()->addTimelinePlayback(playback);

Configuring timelines using the Kanzi Engine API

A timeline consists of a series of iterations played successively, starting at a specified start time. Each iteration is a continuous portion of timeline content which Kanzi plays in a specific manner. Timeline content can consist of one or more animations, or child timelines.

Timeline playback properties allow you to define how Kanzi plays timeline content. For example, you can set the speed, number of repetitions and playback direction of animations. Kanzi applies timeline properties in this order:

  1. Clipping properties set the portion of timeline content played in an iteration:
  2. Duration scale sets how long the (clipped) timeline content takes to play.
    For example, if you set duration scale to 2, the timeline content takes twice as long to play as it is defined in the timeline content.
    The clipped and duration-scaled timeline content represents the content of an iteration.
  3. Direction behavior sets in which direction the iteration content plays. Set direction behavior to:
  4. Repeat count sets how many times the iteration content is repeated. Set repeat count to 0 to make the iteration repeat indefinitely or until it is stopped.
  5. Start time sets when the first iteration of the timeline starts to play. Set start time to:

A timeline applies its content only after its global time exceeds the start time property of the timeline. After Kanzi has played the timeline until the end, the timeline applies its content from the end indefinitely until it is removed. If you have a parallel timeline with repeat count set to multiple repeats, and you add to it a timeline with a non-zero positive start time, the child timeline starts playing in the beginning of each iteration of the parallel timeline only after its global time exceeds its start time.

Note that not all combinations of timeline playback properties are valid. For example, if you set the repeat count of a timeline to infinite and add the timeline to a parallel timeline as a child timeline, the content duration of the parallel timeline becomes infinite. In this case it is not allowed to set the direction behavior of the parallel timeline to reverse, because it does not make sense to revert infinite content. If you do set the direction behavior to reverse, Kanzi Engine internally reverts it to normal and prints a warning message to the log.

To set the clipping of a timeline:

// Set the clip start time to 500 milliseconds. When the animation starts, it skips the first 500 milliseconds.
timeline->setClipStartTime(chrono::milliseconds(500));
// Set the duration of the clip to 1000 milliseconds. The animation ends after 1000 milliseconds of playback at position 1500 milliseconds.
timeline->setClipDuration(chrono::milliseconds(1000));

To set the duration, direction behavior and repeat count of a timeline:

// Set the duration scale of the animation to 2. The animation takes twice as long to play as it is defined in the animation. 
timeline->setDurationScale(2.0f);
// Set the direction behavior of the animation to ping pong. When the animation reaches the end it will bounce back and continue to the beginning in reverse direction.
timeline->setDirectionBehavior(Timeline::DirectionBehaviorPingPong);
// Set the repeat count to 2. When the animation reaches the beginning again after the ping pong playback is finished, it will repeat the animation once more.
timeline->setRepeatCount(2);
// Set the repeat count to infinity. The animation will play forever or until it is explicitly stopped.
timeline->setRepeatCount(0);

To set the start time of a timeline:

// Set the timeline start time to 100 milliseconds. The timeline starts to play its first iteration when its global time reaches 100 milliseconds.
timeline->setStartTime(chrono::milliseconds(100));

See also

Animation system

Tutorial: Create keyframe animations

Creating keyframe animations

Changing the interpolation mode between keyframes

Editing timeline sequences

Editing animation clips

Animations best practices